package com.jdiv.samples.truco.server;

import java.net.*;
import java.io.*;
import java.util.*;


public class ServidorUDP{
	//Socket UDP
	DatagramSocket socket; 
	//el puerto de escucha del servidor ser el 40000
	final int PUERTO=40000;
	//arreglo que contendra todos los usuarios conectados
	private ArrayList<Jugador> jugadorOnline=new ArrayList<Jugador>();
	
	public ServidorUDP(){
	escuchaServer();
	}
	
	public void escuchaServer(){

	try{
	
	//Creamos el socket UDP del servidor en el pueto asociado
	socket = new DatagramSocket(PUERTO);
	System.out.println("Servidor Activo");
	
	//implementacion del protocolo del servidor en un bucle infinito
		while (true) {
		DatagramPacket recibido = new DatagramPacket(new byte [1024],1024);
			
			//llega un datagrama
			socket.receive(recibido);
		
			System.out.print("[RCV:" + recibido.getAddress().getHostAddress());
			System.out.print(":" + recibido.getPort());
			
			String received = new String (recibido.getData());
			
			System.out.println("]: "+received.replaceAll("[^a-zA-Z0-9.;]",""));
			
			String rcbSplit[]=received.split(";");
			int cabecera=Integer.parseInt(rcbSplit[0]);
			compruebaMsg(cabecera,recibido.getAddress(),recibido.getPort(),received);
						
					
			}
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	public void compruebaMsg(int cabecera,InetAddress ip,int puerto, String msg){
		
		String msgSplit[]=msg.split(";");
		
		switch (cabecera){
		case 1: //Login
		String nombre=msgSplit[1];
		String modelo=msgSplit[2];
	//	long   longIp=Long.parseLong(msgSplit[3]);
	    long longIp=parseLongIp(ip);
	  	insertaJugador(nombre,modelo,longIp,ip,puerto,msg);
		
		break;
		case 2: //Movimiento
       //"2;1;x;y;z;"
		for (int i=0;i<jugadorOnline.size();i++){
		Jugador player=jugadorOnline.get(i);
			if (player.getIp().equals(ip) && player.getPuerto()==puerto){
				String	mensaje="2;"+player.getLongIp()+";"+player.getPuerto()+";"+msgSplit[1]+";";
				enviarMensajes(mensaje,ip,puerto);
				actualizaMovimiento(player,Integer.parseInt(msgSplit[1]));
			}
		}
		break;
		
		default:
		//enviarMensajes(msg);
		break;
		
		}
		
	}
	
	public void insertaJugador(String nombre, String modelo, long longIp, InetAddress ip, int puerto,String msg){
		
		boolean existe=false;
	
		
		for (int i=0;i<jugadorOnline.size();i++){
		Jugador playerExiste=jugadorOnline.get(i);
		  if (nombre.equals(playerExiste.getNombre())){
		  	existe=true;
		  }	
		}
		
		//Si no existe, creamos un nuevo jugador
		if (!existe){
		Jugador player=new Jugador(longIp,ip,puerto,nombre,modelo);
		enviarMensaje("1;"+player.getNombre()+";"+player.getModelo()+";"+player.getLongIp()+";"+player.getPuerto()+";0;0;0;0;",ip,puerto);
		
		//Buscamos a todos los jugadores conectados
		for (int i=0;i<jugadorOnline.size();i++){
		Jugador playerInfo=jugadorOnline.get(i);
		
		//Creamos un mensaje con la informacion de cada jugador conectado
		String msgInfo="1;"+playerInfo.getNombre()+";"+playerInfo.getModelo()+";"+playerInfo.getLongIp();
		msgInfo+=";"+playerInfo.getPuerto()+";"+playerInfo.getPosX()+";"+playerInfo.getPosY()+";"+playerInfo.getPosZ();
		msgInfo+=";"+playerInfo.getYaw();
		
		//enviamos esta informacion al jugador que acaba de crearse
		//para que pueda cargar todos los jugadores conectados
		enviarMensaje(msgInfo,ip,puerto);
		
		}
		//le mandamos al resto de los jugadores, la informacion
		//de que hay un nuevo jugador
		enviarMensajesAll("1;"+player.getNombre()+";"+player.getModelo()+";"+player.getLongIp()+";"+player.getPuerto()+";0;0;0;0;");
	
		//agreamos el jugador a la lista
		jugadorOnline.add(player);
		}	
	}
	
 	public void enviarMensajes(String msg,InetAddress ip,int puerto){
		try{
		
				for (int i=0;i<jugadorOnline.size();i++){
				
					Jugador player=jugadorOnline.get(i);
					if (player.getIp()!=ip && player.getPuerto()!=puerto){
				
						
				 	//se prepara el mensaje a enviar con la fecha del sistema
					byte byteMsg[]=msg.getBytes();
					
					//se crea el datagrama que contendra el mensaje 
					DatagramPacket paquete=new DatagramPacket(byteMsg,byteMsg.length,player.getIp(),player.getPuerto());
					
					
					System.out.println("[ENV]: "+msg);
					//se le envia al cliente
					socket.send(paquete);
			    	}
					
				}
		
			}catch(IOException e){
			e.printStackTrace();
		}
			
	}
	
	public void enviarMensajesAll(String msg){
		try{
		
				for (int i=0;i<jugadorOnline.size();i++){
				
					Jugador player=jugadorOnline.get(i);
					
				 	//se prepara el mensaje a enviar con la fecha del sistema
					byte byteMsg[]=msg.getBytes();
					
					//se crea el datagrama que contendra el mensaje 
					DatagramPacket paquete=new DatagramPacket(byteMsg,byteMsg.length,player.getIp(),player.getPuerto());
					
					
					System.out.println("[ENV]: "+msg);
					//se le envia al cliente
					socket.send(paquete);
					
					
				}
		
			}catch(IOException e){
			e.printStackTrace();
		}
			
	}

	public void enviarMensaje(String msg,InetAddress ip, int puerto){
	try{
		byte byteMsg[]=msg.getBytes();
			
		//se crea el datagrama que contendr al mensaje 
		DatagramPacket paquete=new DatagramPacket(byteMsg,byteMsg.length,ip,puerto);
					
		System.out.println("[ENV]: "+msg);
		
		//se le envia al cliente
		socket.send(paquete);
		
		
	
		}catch(IOException e){
			e.printStackTrace();
		}	
	}
	
	private void actualizaMovimiento(Jugador player,int direccion){
	double playerX,playerY,playerZ,playerYaw;
	
	switch(direccion){
	case 1:  //Forward
		playerZ=player.getPosZ();
		playerZ+=.5;
		player.setPosZ(playerZ);
		break;
	case 2:  //Back
		playerZ=player.getPosZ();
		playerZ-=.5;
		player.setPosZ(playerZ);
		break;
	case 3:  //Left
		playerYaw=player.getYaw();
		playerYaw+=4;
		player.setYaw(playerYaw);
		break;
	case 4:  //Right
		playerYaw=player.getYaw();
		playerYaw-=4;
		player.setYaw(playerYaw);
		break;
					
		}
	}
	
	private long parseLongIp(InetAddress normalip) { 
	
	String sIP[]= normalip.getHostAddress().split("\\.");
	
	int ip[]=new int[4];
		
		for (int i=0;i<sIP.length;i++){
		
			ip[i]=Integer.parseInt(sIP[i]);
		
				}
			
		long longIP = (ip[3] << 24) | (ip[2] << 16) | (ip[1] << 8) | (ip[0]);
		
		return longIP;
	}
	public static void main(String args[]){
		ServidorUDP sudp= new ServidorUDP();
		
	}
} 
